home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C
/
Applications
/
Python 1.3.3
/
Python 133 SRC
/
Extensions
/
img
/
imgpgmmodule.c
< prev
next >
Wrap
Text File
|
1995-12-21
|
14KB
|
578 lines
/***********************************************************
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#include "Python.h"
#include "import.h"
#include "pgm.h"
/* The image formats we support */
static PyObject *format_grey, *format_xgrey, *format_grey_b2t, *format_choices;
extern PyObject *getimgformat(); /* Get foirmat by name */
/*
** Since PBMPLUS error handling is abysmal (print message, exit),
** there is a modified version that has (slightly) better error
** handling. Contact jack@cwi.nl if you want it. Define PBMNEWERROR
** if you have the modified pbmplus.
**
** If you don't have it the first pbm error will abort you python
** program.
*/
#define PBMNEWERROR
#ifndef PBMNEWERROR
#define PGM_END
#define PGM_START if (0) {
#define PGM_ENDSTART }
#else
#include <setjmp.h>
jmp_buf pgmerrenv;
char pgmerrstr[1000];
#define PGM_END pm_setmsghandler(0); pm_setexithandler(0);
#define PGM_START if ( setjmp(pgmerrenv) != 0 ) { \
PyErr_SetString(errobject, pgmerrstr); \
*pgmerrstr = '\0'; \
PGM_END
#define PGM_ENDSTART return 0; \
} \
pm_setmsghandler(my_pmerr); \
pm_setexithandler(my_pmexit);
static void
my_pmerr(str)
char *str;
{
strncpy(pgmerrstr, str, 999);
}
static void
my_pmexit()
{
longjmp(pgmerrenv, 1);
}
#endif /* PBMNEWERROR */
/* Pgm objects */
typedef struct {
PyObject_HEAD
PyObject *dict; /* Attributes dictionary */
int is_reader; /* TRUE if this is a reader */
char *filename; /* filename of the image file */
FILE *filep;
gray maxval;
int format;
} pgmobject;
static PyObject *errobject;
staticforward PyTypeObject Pgmtype;
#define is_pgmobject(v) ((v)->ob_type == &Pgmtype)
static char doc_pgm[] = "This object reads/writes PGM files\n"
"The 'width', 'height' and 'format' attributes describe the picture\n"
"For writers, setting 'forceplain' creates an ASCII PGM file.";
/* Routine to easily obtain C data from the dict python data */
int
pgmselfattr(self, name, fmt, ptr, wanterr)
pgmobject *self;
char *name;
char *fmt;
void *ptr;
int wanterr;
{
PyObject *obj;
char errbuf[100];
obj = PyDict_GetItemString(self->dict, name);
if ( obj == NULL ) {
if ( wanterr ) {
sprintf(errbuf, "Required attribute '%s' not set", name);
PyErr_SetString(errobject, errbuf);
return 0;
} else {
PyErr_Clear();
return 0;
}
}
if ( !PyArg_Parse(obj, fmt, ptr) ) {
if ( !wanterr )
PyErr_Clear();
return 0;
}
return 1;
}
/* Routine to easily insert integer into dictionary */
pgmsetintattr(self, name, value)
pgmobject *self;
char *name;
int value;
{
PyObject *obj;
int rv;
obj = PyInt_FromLong(value);
rv = PyDict_SetItemString(self->dict, name, obj);
Py_DECREF(obj);
return rv;
}
static pgmobject *
newpgmobject()
{
pgmobject *xp;
xp = PyObject_NEW(pgmobject, &Pgmtype);
if (xp == NULL)
return NULL;
xp->dict = PyDict_New();
xp->filename = NULL;
xp->filep = NULL;
return xp;
}
static int
initpgmreader(self, name)
pgmobject *self;
char *name;
{
char *name_copy;
int cols, rows;
gray old_pbmmaxval;
if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
PyErr_NoMemory();
return 0;
}
strcpy(name_copy, name);
self->filename = name_copy;
self->is_reader = 1;
if ((self->filep = fopen(self->filename, "rb")) == NULL ) {
PyErr_SetFromErrno(PyExc_IOError);
return 0;
}
PGM_START
fclose(self->filep);
self->filep = 0;
return 0;
PGM_ENDSTART
old_pbmmaxval = pgm_pbmmaxval;
pgm_pbmmaxval = 0xff; /* XXXX Correct for grey/grey_b2t formats */
pgm_readpgminit(self->filep, &cols, &rows, &self->maxval,
&self->format);
pgm_pbmmaxval = old_pbmmaxval;
PGM_END
pgmsetintattr(self, "width", cols);
pgmsetintattr(self, "height", rows);
PyDict_SetItemString(self->dict, "format", format_grey);
PyDict_SetItemString(self->dict, "format_choices", format_choices);
if ( PyErr_Occurred() )
return 0;
return 1;
}
static int
initpgmwriter(self, name)
pgmobject *self;
char *name;
{
char *name_copy;
if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
PyErr_NoMemory();
return 0;
}
strcpy(name_copy, name);
self->filename = name_copy;
self->filep = NULL;
self->is_reader = 0;
PyDict_SetItemString(self->dict, "format", format_grey);
PyDict_SetItemString(self->dict, "format_choices", format_choices);
if( PyErr_Occurred())
return 0;
return 1;
}
/* Pgm methods */
static void
pgm_dealloc(xp)
pgmobject *xp;
{
Py_XDECREF(xp->dict);
if( xp->filename )
free(xp->filename);
if( xp->filep )
fclose(xp->filep);
PyMem_DEL(xp);
}
static char doc_read[] = "Read the actual data, returns a string";
static PyObject *
pgm_read(self, args)
pgmobject *self;
PyObject *args;
{
int i, w, h, toptobottom, rowlen;
PyObject *rv;
char *datap;
gray *pixelrow;
PyObject *fmt;
if (!PyArg_ParseTuple(args,""))
return NULL;
if (!self->is_reader) {
PyErr_SetString(errobject, "Cannot read() from writer object");
return NULL;
}
/* XXXX Read data and return it */
/* XXXX Get args from self->dict and write the data */
if ( !pgmselfattr(self, "width", "i", &w, 1) ||
!pgmselfattr(self, "height", "i", &h, 1) ||
!pgmselfattr(self, "format", "O", &fmt, 1) )
return NULL;
if ( fmt == format_grey || fmt == format_xgrey )
toptobottom = 1;
else if ( fmt == format_grey_b2t )
toptobottom = 0;
else {
PyErr_SetString(errobject, "Unsupported image format");
return NULL;
}
pixelrow = 0;
rv = 0;
PGM_START
if ( pixelrow )
pbm_freerow(pixelrow);
if ( rv )
Py_DECREF(rv);
return NULL;
PGM_ENDSTART
pixelrow=pgm_allocrow(w);
if ( fmt == format_xgrey )
rowlen = w;
else
rowlen = (w+3) & ~3; /* SGI images have 32bit aligned rows */
if ( (rv=PyString_FromStringAndSize(0, rowlen*h)) == NULL ) {
pbm_freerow(pixelrow);
return NULL;
}
datap = PyString_AsString(rv);
if ( !toptobottom ) {
datap = datap + rowlen*(h-1);
rowlen = -rowlen;
}
while( h > 0 ) {
pgm_readpgmrow(self->filep, pixelrow, w, self->maxval,
self->format);
for(i=0; i<w; i++)
datap[i] = pixelrow[i];
/* zero-out remaining bytes */
while(i<rowlen)
datap[i++] = 0;
datap += rowlen;
h -= 1;
}
PGM_END
pbm_freerow(pixelrow);
return rv;
}
static char doc_write[] = "Write (string) data to the PGM file";
static PyObject *
pgm_write(self, args)
pgmobject *self;
PyObject *args;
{
unsigned char *data;
int datalen;
int i, w, h, rowlen;
PyObject *fmt;
gray *pixelrow;
int forceplain;
FILE *filep;
if (!PyArg_ParseTuple(args, "s#", &data, &datalen))
return NULL;
if (self->is_reader) {
PyErr_SetString(errobject, "Cannot write() to reader object");
return NULL;
}
/* XXXX Get args from self->dict and write the data */
if ( !pgmselfattr(self, "width", "i", &w, 1) ||
!pgmselfattr(self, "height", "i", &h, 1) ||
!pgmselfattr(self, "format", "O", &fmt, 1) )
return NULL;
forceplain = 0;
pgmselfattr(self, "forceplain", "i", &forceplain, 0);
if ( fmt == format_xgrey )
rowlen = w;
else
rowlen = (w+3) & ~3; /* For 32bit alignment of rows */
if ( fmt != format_grey && fmt != format_xgrey &&
fmt != format_grey_b2t ) {
PyErr_SetString(errobject, "Unsupported image format");
return NULL;
}
if( rowlen*h != datalen ) {
PyErr_SetString(errobject, "Incorrect datasize");
return NULL;
}
if ( fmt == format_grey_b2t ) {
data = data + rowlen*(h-1);
rowlen = -rowlen;
}
if ((filep = fopen(self->filename, forceplain?"w":"wb")) == NULL) {
PyErr_SetFromErrno(PyExc_IOError);
return 0;
}
#ifdef macintosh
setfiletype(self->filename, '????', 'PPGM');
#endif
pixelrow = 0;
PGM_START
if ( pixelrow )
pbm_freerow(pixelrow);
fclose(filep);
return NULL;
PGM_ENDSTART
pixelrow=pgm_allocrow(w);
pgm_writepgminit(filep, w, h, 0xff, forceplain);
while( h > 0 ) {
for(i=0; i<w; i++)
pixelrow[i] = data[i];
pgm_writepgmrow(filep, pixelrow, w, 0xff, forceplain);
data += rowlen;
h -= 1;
}
PGM_END
pbm_freerow(pixelrow);
if (fclose(filep) != 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef pgm_methods[] = {
{"read", (PyCFunction)pgm_read, 1, doc_read},
{"write", (PyCFunction)pgm_write, 1, doc_write},
{NULL, NULL} /* sentinel */
};
static PyObject *
pgm_getattr(xp, name)
pgmobject *xp;
char *name;
{
PyObject *v;
if (xp->dict != NULL) {
if ( strcmp(name, "__dict__") == 0 ) {
Py_INCREF(xp->dict);
return xp->dict;
}
if ( strcmp(name, "__doc__") == 0 ) {
return PyString_FromString(doc_pgm);
}
v = PyDict_GetItemString(xp->dict, name);
if (v != NULL) {
Py_INCREF(v);
return v;
}
}
return Py_FindMethod(pgm_methods, (PyObject *)xp, name);
}
static int
pgm_setattr(xp, name, v)
pgmobject *xp;
char *name;
PyObject *v;
{
if (xp->dict == NULL) {
xp->dict = PyDict_New();
if (xp->dict == NULL)
return -1;
}
if (v == NULL) {
int rv = PyDict_DelItemString(xp->dict, name);
if (rv < 0)
PyErr_SetString(PyExc_AttributeError,
"delete non-existing imgpgm attribute");
return rv;
}
else
return PyDict_SetItemString(xp->dict, name, v);
}
static PyTypeObject Pgmtype = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"imgpgm", /*tp_name*/
sizeof(pgmobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)pgm_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)pgm_getattr, /*tp_getattr*/
(setattrfunc)pgm_setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
};
static char doc_newreader[] =
"Return an object that reads the PGM/PBM file passed as argument";
static PyObject *
pgm_newreader(self, args)
PyObject *self;
PyObject *args;
{
char *filename;
pgmobject *obj;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
if ((obj = newpgmobject()) == NULL)
return NULL;
if ( !initpgmreader(obj, filename) ) {
pgm_dealloc(obj);
return NULL;
}
return (PyObject *)obj;
}
static char doc_newwriter[] =
"Return an object that writes the PGM file passed as argument";
static PyObject *
pgm_newwriter(self, args)
PyObject *self;
PyObject *args;
{
char *filename;
pgmobject *obj;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
if ((obj = newpgmobject()) == NULL)
return NULL;
if ( !initpgmwriter(obj, filename) ) {
pgm_dealloc(obj);
return NULL;
}
return (PyObject *)obj;
}
/* List of functions defined in the module */
static struct PyMethodDef pgm_module_methods[] = {
{"reader", pgm_newreader, 1, doc_newreader},
{"writer", pgm_newwriter, 1, doc_newwriter},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initimgpgm) */
static char doc_imgpgm[] =
"Module that reads images from PGM/PBM files and writes to PGM files.";
void
initimgpgm()
{
PyObject *m, *d, *x, *formatmodule, *formatdict;
/* Create the module and add the functions */
m = Py_InitModule("imgpgm", pgm_module_methods);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
errobject = PyString_FromString("imgpgm.error");
PyDict_SetItemString(d, "error", errobject);
x = PyString_FromString(doc_imgpgm);
PyDict_SetItemString(d, "__doc__", x);
/* Get supported formats */
if ((formatmodule = PyImport_ImportModule("imgformat")) == NULL)
Py_FatalError("imgpgm depends on imgformat");
if ((formatdict = PyModule_GetDict(formatmodule)) == NULL)
Py_FatalError("imgformat has no dict");
format_grey = PyDict_GetItemString(formatdict,"grey");
format_xgrey = PyDict_GetItemString(formatdict,"xgrey");
format_grey_b2t = PyDict_GetItemString(formatdict,"grey_b2t");
format_choices = Py_BuildValue("(OOO)", format_grey, format_xgrey,
format_grey_b2t);
/* Initialize pbmplus */
{
int pgm_argc;
static char *pgm_arglist[] = { "pbmplus", 0};
char **pgm_argv;
pgm_argc = 1;
pgm_argv = pgm_arglist;
PGM_START /* { */
Py_FatalError("pbmplus initialization error");
} /* PGM_ENDSTART won't work here, it has return NULL */
pgm_init(&pgm_argc, pgm_argv);
PGM_END
}
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module imgpgm");
}